<script setup lang="ts">
import { ref, computed } from 'vue'
import {
  RECIPE_CONDIMENT_MAP,
  TECHNIQUES_MAP,
  RARITY_MAP,
  GOLD_RUNE,
  SILVER_RUNE,
  BRONZE_RUNE,
} from '@/stores/mappings'
import { getStringKeys, getNumericKeys } from '@/utils/tools'
import { useGameStore } from '@/stores/modules/game'

import type { SelectOption, SelectGroupOption } from 'naive-ui'
import type { RecipeSettings, Techniques, RecipeCondiment } from './types'
import type { Gift } from '@/stores/types'

interface RarityOption extends SelectOption {
  label: string
  value: number
}

interface TechniquesOption extends SelectOption {
  label: string
  value: Techniques
}

interface RecipeCondimentOption extends SelectOption {
  label: string
  value: RecipeCondiment
}

interface MaterialOption extends SelectOption {
  label: string
  value: number
}

interface RuneOption extends SelectOption {
  label: Gift
  value: Gift
}

type RuneGroupOption = SelectGroupOption & {
  children: RuneOption[]
}

const props = defineProps<{
  settings: RecipeSettings
}>()

const emit = defineEmits<{
  (e: 'update:settings', value: RecipeSettings): void
}>()

const materialSearch = ref('')

const rarityOptions = ref<RarityOption[]>(
  getNumericKeys(RARITY_MAP).map((key) => ({
    label: RARITY_MAP[key],
    value: key,
  })),
)

const techniquesOptions = ref<TechniquesOption[]>(
  getStringKeys(TECHNIQUES_MAP).map((key) => ({
    label: TECHNIQUES_MAP[key],
    value: key,
  })),
)

const condimentOptions = ref<RecipeCondimentOption[]>(
  getStringKeys(RECIPE_CONDIMENT_MAP).map((key) => ({
    label: RECIPE_CONDIMENT_MAP[key],
    value: key,
  })),
)

const materialOptions = computed<MaterialOption[]>(() => {
  return useGameStore()
    .materials.map((m) => ({
      label: m.name,
      value: m.materialId,
    }))
    .filter((f) => f.label.includes(materialSearch.value))
})

const runeOptions = ref<RuneGroupOption[]>([
  {
    type: 'group',
    label: '金符文',
    children: GOLD_RUNE.map((m) => ({
      label: m,
      value: m,
    })),
  },
  {
    type: 'group',
    label: '银符文',
    children: SILVER_RUNE.map((m) => ({
      label: m,
      value: m,
    })),
  },
  {
    type: 'group',
    label: '铜符文',
    children: BRONZE_RUNE.map((m) => ({
      label: m,
      value: m,
    })),
  },
])

const rarityDisplay = computed(() => {
  const { rarity } = props.settings
  if (!rarity.length) return ''
  return rarityOptions.value
    .filter((f) => rarity.includes(f.value))
    .map((m) => m.label)
    .join('&')
})

const techniquesDisplay = computed(() => {
  const { techniques } = props.settings
  if (!techniques.length) return ''
  return techniquesOptions.value
    .filter((f) => techniques.includes(f.value))
    .map((m) => m.label)
    .join('&')
})

const condimentDisplay = computed(() => {
  const { condiment } = props.settings
  if (!condiment.length) return ''
  return condimentOptions.value
    .filter((f) => condiment.includes(f.value))
    .map((m) => m.label)
    .join('&')
})

const materialDisplay = computed(() => {
  const { material } = props.settings
  if (!material.length) return ''
  return materialOptions.value
    .filter((f) => material.includes(f.value))
    .map((m) => m.label)
    .join('&')
})

const runeDisplay = computed<string>(() => {
  let result = ''
  const { rune } = props.settings
  if (rune.length) {
    const [gold, silver, bronze] = [GOLD_RUNE, SILVER_RUNE, BRONZE_RUNE]
    const strArr: string[] = []
    if (gold.some((s) => rune.includes(s))) {
      strArr.push('金符文')
    }
    if (silver.some((s) => rune.includes(s))) {
      strArr.push('银符文')
    }
    if (bronze.some((s) => rune.includes(s))) {
      strArr.push('铜符文')
    }
    result = strArr.join('&')
  }
  return result
})

function updateCondiment(value: RecipeCondiment[]) {
  const condiment = value.length > 0 ? [value[value.length - 1]] : []
  emit('update:settings', { ...props.settings, condiment })
}

function updateMaterial(value: number[]) {
  const material = value.length > 0 ? [value[value.length - 1]] : []
  emit('update:settings', { ...props.settings, material })
}
</script>

<template>
  <n-flex>
    <n-popselect
      class="w-[100px]"
      v-model:value="settings.rarity"
      :options="rarityOptions"
      trigger="hover"
      multiple
    >
      <n-button class="min-w-[100px]">
        <span class="mx-[4px]">星级</span>
        <n-gradient-text type="info">{{ rarityDisplay }}</n-gradient-text>
      </n-button>
    </n-popselect>
    <n-popselect
      class="w-[100px]"
      v-model:value="settings.techniques"
      :options="techniquesOptions"
      trigger="hover"
      multiple
    >
      <n-button class="min-w-[100px]">
        <span class="mx-[4px]">技法</span>
        <n-gradient-text type="info">{{ techniquesDisplay }}</n-gradient-text>
      </n-button>
    </n-popselect>
    <n-popselect
      class="w-[100px]"
      :value="settings.condiment"
      :options="condimentOptions"
      trigger="hover"
      multiple
      :on-update:value="updateCondiment"
    >
      <n-button class="min-w-[100px]">
        <span class="mx-[4px]">调料</span>
        <n-gradient-text type="info">{{ condimentDisplay }}</n-gradient-text>
      </n-button>
    </n-popselect>
    <n-popselect
      class="w-[120px]"
      :value="settings.material"
      :options="materialOptions"
      trigger="hover"
      multiple
      :on-update:value="updateMaterial"
      scrollable
    >
      <n-button class="min-w-[120px]">
        <span class="mx-[4px]">食材</span>
        <n-gradient-text type="info">{{ materialDisplay }}</n-gradient-text>
      </n-button>
      <template #header>
        <n-input v-model:value="materialSearch" type="text" size="small" clearable />
      </template>
    </n-popselect>
    <n-popselect
      class="w-[120px]"
      v-model:value="settings.rune"
      :options="runeOptions"
      trigger="hover"
      multiple
      scrollable
    >
      <n-button class="min-w-[120px]">
        <span class="mx-[4px]">符文</span>
        <n-gradient-text type="info">{{ runeDisplay }}</n-gradient-text>
      </n-button>
    </n-popselect>
  </n-flex>
</template>

<style lang="scss" scoped></style>
